package com.mmall.service.impl;

import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Lists;
import com.google.common.collect.Multimap;
import com.google.common.collect.Sets;
import com.mmall.dao.SysAclMapper;
import com.mmall.dao.SysAclModuleMapper;
import com.mmall.dao.SysDeptMapper;
import com.mmall.dto.AclDto;
import com.mmall.dto.AclModuleDto;
import com.mmall.dto.DeptLevelDto;
import com.mmall.pojo.SysAcl;
import com.mmall.pojo.SysAclModule;
import com.mmall.pojo.SysDept;
import com.mmall.service.ISysCoreService;
import com.mmall.service.ISysTreeService;
import com.mmall.util.LevelUtil;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;

/**
 * @Author wangtengyu
 * @Create 2018-03-07-16:03
 */
@Service("iSysTreeService")
public class SysTreeServiceImpl implements ISysTreeService {

    @Autowired
    private SysDeptMapper sysDeptMapper;

    @Autowired
    private SysAclModuleMapper sysAclModuleMapper;

    @Autowired
    private SysAclMapper sysAclMapper;

    @Autowired
    private ISysCoreService iSysCoreService;


    /**
     * 生成dto对象list(部门)
     *
     * @return
     */
    public List<DeptLevelDto> deptTree() {
        List<SysDept> sysDeptList = sysDeptMapper.selectAll();
        List<DeptLevelDto> dtoList = Lists.newArrayList();
        for (SysDept sysDept : sysDeptList) {
            DeptLevelDto dto = DeptLevelDto.adpat(sysDept);
            dtoList.add(dto);
        }
        return deptListToTree(dtoList);
    }


    public List<DeptLevelDto> deptListToTree(List<DeptLevelDto> deptLevelDtoList) {
        //如果为空,说明没有部门，直接返回一个空集合
        if (CollectionUtils.isEmpty(deptLevelDtoList)) {
            return Lists.newArrayList();
        }
        //如果不为空 需要把节点分level存储
        Multimap<String, DeptLevelDto> levelDeptMap = ArrayListMultimap.create();

        //封装一个跟level dto对象集合
        List<DeptLevelDto> rootList = Lists.newArrayList();

        for (DeptLevelDto deptLevelDto : deptLevelDtoList) {
            levelDeptMap.put(deptLevelDto.getLevel(), deptLevelDto);
            if (LevelUtil.ROOT.equals(deptLevelDto.getLevel())) {
                rootList.add(deptLevelDto);
            }
        }
        Collections.sort(rootList, deptSeqComparator);
        transformDeptTree(rootList, LevelUtil.ROOT, levelDeptMap);
        return rootList;


    }


    /**
     * 递归生成
     * 循环设置下一层级到上一层级的某个元素的集合中，初始的层级是root层级
     *
     * @param deptLevelDtoList
     * @param level            当前层级，用于获取下一层级
     * @param deptLevelMap     存储了level与对应dto对象的map
     */
    public void transformDeptTree(List<DeptLevelDto> deptLevelDtoList, String level, Multimap<String, DeptLevelDto> deptLevelMap) {
        for (int i = 0; i < deptLevelDtoList.size(); i++) {
            //要设置它的deptlevelList啊
            DeptLevelDto deptLevelDto = deptLevelDtoList.get(i);
            //要把跟节点的deptLevelDtoList设置上,就要获取它下一层级的level,从而获取下一层级的元素
            String nextLevel = LevelUtil.getLevel(level, deptLevelDto.getId());
            //获取到下一层级部门集合
            List<DeptLevelDto> tempDeptlist = (List<DeptLevelDto>) deptLevelMap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(tempDeptlist)) {//递归的出口
                Collections.sort(tempDeptlist, deptSeqComparator);
                deptLevelDto.setDeptList(tempDeptlist);
                transformDeptTree(tempDeptlist, nextLevel, deptLevelMap);
            }
        }
    }


    /**
     * 生成树形结构(权限模块)
     *
     * @return
     */
    public List<AclModuleDto> aclModuleTree() {
        List<SysAclModule> aclModuleList = sysAclModuleMapper.selectAll();
        List<AclModuleDto> aclModuleDtoList = Lists.newArrayList();
        for (SysAclModule sysAclModule : aclModuleList) {
            AclModuleDto aclModuleDto = AclModuleDto.adapt(sysAclModule);
            aclModuleDtoList.add(aclModuleDto);
        }
        return aclModuleListToTree(aclModuleDtoList);
    }

    public List<AclModuleDto> aclModuleListToTree(List<AclModuleDto> aclModuleDtoList) {
        if (CollectionUtils.isEmpty(aclModuleDtoList)) {
            return Lists.newArrayList();
        }
        Multimap<String, AclModuleDto> aclLevelMap = ArrayListMultimap.create();

        List<AclModuleDto> rootList = Lists.newArrayList();

        for (AclModuleDto aclModuleDto : aclModuleDtoList) {
            aclLevelMap.put(aclModuleDto.getLevel(), aclModuleDto);
            if (LevelUtil.ROOT.equals(aclModuleDto.getLevel())) {
                rootList.add(aclModuleDto);
            }

        }
        Collections.sort(rootList, aclModuleSeqComparator);
        transformAclModuleTree(rootList, LevelUtil.ROOT, aclLevelMap);
        return rootList;
    }

    public void transformAclModuleTree(List<AclModuleDto> aclModuleDtoList, String level, Multimap<String, AclModuleDto> aclLevelMap) {
        for (int i = 0; i < aclModuleDtoList.size(); i++) {
            AclModuleDto aclModuleDto = aclModuleDtoList.get(i);
            String nextLevel = LevelUtil.getLevel(level, aclModuleDto.getId());
            List<AclModuleDto> aclModuleList = (List<AclModuleDto>) aclLevelMap.get(nextLevel);
            if (CollectionUtils.isNotEmpty(aclModuleList)) {
                Collections.sort(aclModuleList, aclModuleSeqComparator);
                aclModuleDto.setAclModuleList(aclModuleList);
                transformAclModuleTree(aclModuleList, nextLevel, aclLevelMap);
            }
        }
    }


    public List<AclModuleDto> roleAclTree(int roleId) {
        //获取当前登录用户权限点(用于判断是否可以授权,可以的话就可以选择,不可以的话就不可以选择)
        List<SysAcl> userAclList = iSysCoreService.getCurrentUserAclList();
        //获取角色对应权限点(用于回显)
        List<SysAcl> roleAclList = iSysCoreService.getRoleAclList(roleId);
        //获取系统所有权限(封装成acldto对象,拥有判断属性)
        List<AclDto> aclDtoList = Lists.newArrayList();

        //设置权限点集合
        Set<Integer> userAclIdSet = Sets.newHashSet();
        Set<Integer> roleAclIdSet = Sets.newHashSet();

        //Set<Integer> roleAclIdSet = Sets.newHashSet(userAclList); 这样类型匹配不上 不是取得id
        //Set<Integer> userAclIdSet1=userAclList.stream().map(sysAcl->sysAcl.getId()).collect(Collectors.toSet()); lambada表达式
        createAclSet(userAclList, userAclIdSet);
        createAclSet(roleAclList, roleAclIdSet);

        List<SysAcl> aclList = sysAclMapper.getAll();
        for (SysAcl acl : aclList) {
            AclDto aclDto = AclDto.adapt(acl);
            if (userAclIdSet.contains(acl.getId())) {
                aclDto.setHasAcl(true);
            }
            if (roleAclIdSet.contains(acl.getId())) {
                aclDto.setChecked(true);
            }
            aclDtoList.add(aclDto);
        }
        return aclListToTree(aclDtoList);
    }

    public List<AclModuleDto> aclListToTree(List<AclDto> aclDtoList) {
        if (CollectionUtils.isEmpty(aclDtoList)) {
            return Lists.newArrayList();
        }
        List<AclModuleDto> aclModuleDtoList = aclModuleTree();

        if(CollectionUtils.isEmpty(aclModuleDtoList)){
            return Lists.newArrayList();
        }

        Multimap<Integer, AclDto> moduleIdAclMap = ArrayListMultimap.create();
        for (AclDto aclDto : aclDtoList) {
            if (aclDto.getStatus() == 1) {
                moduleIdAclMap.put(aclDto.getAclModuleId(), aclDto);
            }
        }

        bindAclWithAclModule(aclModuleDtoList, moduleIdAclMap);

        return aclModuleDtoList;


    }

    /**
     * 将权限绑定到权限模块
     *
     * @param aclModuleDtoList
     * @param moduleIdAclMap
     */
    public void bindAclWithAclModule(List<AclModuleDto> aclModuleDtoList, Multimap<Integer, AclDto> moduleIdAclMap) {
        for(AclModuleDto aclModuleDto:aclModuleDtoList){
            List<AclDto> aclDtoList= (List<AclDto>) moduleIdAclMap.get(aclModuleDto.getId());
            if(CollectionUtils.isNotEmpty(aclDtoList)){
                Collections.sort(aclDtoList,aclSeqComparator);
                aclModuleDto.setAclList(aclDtoList);
            }
            bindAclWithAclModule(aclModuleDto.getAclModuleList(),moduleIdAclMap);
        }
    }

    /**
     * 通过权限集合设置权限id集合
     *
     * @param aclList
     * @param aclIdSet
     */
    public void createAclSet(List<SysAcl> aclList, Set<Integer> aclIdSet) {
        for (SysAcl acl : aclList) {
            aclIdSet.add(acl.getId());
        }
    }


    /**
     * 部门排序
     */
    public Comparator<DeptLevelDto> deptSeqComparator = new Comparator<DeptLevelDto>() {
        @Override
        public int compare(DeptLevelDto o1, DeptLevelDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    /**
     * 权限模块排序
     */
    public Comparator<AclModuleDto> aclModuleSeqComparator = new Comparator<AclModuleDto>() {
        @Override
        public int compare(AclModuleDto o1, AclModuleDto o2) {
            return o1.getSeq() - o2.getSeq();
        }
    };

    /**
     * 权限排序
     */
    public Comparator<AclDto> aclSeqComparator=new Comparator<AclDto>() {
        @Override
        public int compare(AclDto o1, AclDto o2) {
            return o1.getSeq()-o2.getSeq();
        }
    };
}
